#ifndef __SCNS_CIRCULARQUEUE_H__
#define __SCNS_CIRCULARQUEUE_H__

#include "ScnsConfig.h"

#if defined(SCNS_CIRCULAR_QUEUE_ENABLE)&&SCNS_CIRCULAR_QUEUE_ENABLE==1

#include "ScnsYing.h"

#define ScnsCircularQueue(DataType,LengthType,name,size)    \
    struct                                                  \
    {                                                       \
        DataType    array[size];                            \
        LengthType  head,tail;                              \
        enum                                                \
        {                                                   \
            name##_EMPTY,                                   \
            name##_NORMAL,                                  \
            name##_FULL,                                    \
        }status;                                            \
    }name

#define scnsCircularQueueIsFull(pre,name) ((pre).name.status==name##_FULL)
#define scnsCircularQueueIsEmpty(pre,name) ((pre).name.status==name##_EMPTY)
#define scnsCircularQueueGet(pre,name,i) ((pre).name.array[i])
#define scnsCircularQueueGetNewestN(pre,name,size) (((pre).name.tail==0?(size):(pre).name.tail)-1)

#define scnsCircularQueueClear(pre,name) do{(pre).name.head=0;(pre).name.tail=0;(pre).name.status=name##_EMPTY;}while(0)
#define scnsCircularQueueInit(pre,name)     \
    do{                                     \
        (pre).name.head=0;                  \
        (pre).name.tail=0;                  \
        (pre).name.status=name##_EMPTY;     \
    }while(0)

#define scnsCircularQueuePush(pre,name,size,data)                                       \
    do{if(!scnsCircularQueueIsFull(pre,name))                                           \
    {                                                                                   \
        (pre).name.array[(pre).name.tail]=data;                                         \
        ++(pre).name.tail;                                                              \
        (pre).name.tail%=(size);                                                        \
        (pre).name.status=((pre).name.tail==(pre).name.head)?name##_FULL:name##_NORMAL; \
    }}while(0)
#define scnsCircularQueuePop(pre,name,size,data)                                            \
    do{if(!scnsCircularQueueIsEmpty(pre,name))                                              \
    {                                                                                       \
        (data)=(pre).name.array[(pre).name.head];                                           \
        ++(pre).name.head;                                                                  \
        (pre).name.head%=(size);                                                            \
        (pre).name.status=((pre).name.head==(pre).name.tail)?name##_EMPTY:name##_NORMAL;    \
    }}while(0)
#define scnsCircularQueuePopReturn(pre,name,size,data,successReturn,failReturn)                     \
    do{if(!scnsCircularQueueIsEmpty(pre,name))                                                      \
    {                                                                                               \
        (data)=(pre).name.array[(pre).name.head];                                                   \
        ++(pre).name.head;                                                                          \
        (pre).name.head%=(size);                                                                    \
        (pre).name.status=((pre).name.head==(pre).name.tail)?name##_EMPTY:name##_NORMAL;            \
        return successReturn;                                                                       \
    }                                                                                               \
    else                                                                                            \
    {                                                                                               \
        return failReturn;                                                                          \
    }}while(0)

#endif

#endif
